*******************
*This code replicates the analysis presented in the following article and related appendixes:

*Article: What Influences Citizen Forecasts? The Effects of Information, Elite Cues, and Social Cues
*Journal: Political Behavior
*Authors: Davide Morisi and Thomas Leeper
*Date: June 27, 2022

******************

*OBSERVATIONAL ANALYSIS AND APPENDIX A (YOUGOV DATA)

cd "C:\Users\Davide Morisi\Dropbox\research_inprogress\Citizen_forecasts"

use "Replication\data\yougov_recoded.dta", clear

*covariates
gen age10 = Age/10
gen day_int2 = day_int+1
global demo "i.female age10 ib2.ethnicity i.income6"
*additional variables
fre att_high vote3 day_int2 party4_des treatment_all



**********
*Figure 1: Forecast share of “Leave” votes
twoway histogram forecast100 if treatment_all==1, graphregion(color(white)) ///
 yscale(range(0(.01).06)) ylabel(0(.01).06) ytitle("Density") ///
 xscale(range(0(10)100)) xlabel(0(10)100) xtitle("Forecast share of Leave voters") || ///
(scatteri 0 50.6 .06 50.6, c(l) m(i) lpattern(dash) lcolor(gs2)) || ///
(scatteri 0 51.9 .06 51.9, c(l) m(i) lpattern(dash) lcolor(gs10)) || ///
(kdensity forecast100 if treatment_all==1, lcolor(black) ///
text(.058 42 "Mean: 50.6%", color(gs2) orientation(horizontal) placement(6)) ///
text(.005 62 "True result: 51.9%", color(gs10) orientation(horizontal) placement(6)))


*Figure A1: Forecast share of “Leave” votes (trimmed values)
twoway histogram forecast_trim if treatment_all==1, graphregion(color(white)) ///
 yscale(range(0(.01).07)) ylabel(0(.01).07) ytitle("Density") ///
 xscale(range(10(10)90)) xlabel(10(10)90) xtitle("Forecast share of Leave voters (trimmed values)") || ///
(scatteri 0 50.3 .07 50.3, c(l) m(i) lpattern(dash) lcolor(gs2)) || ///
(scatteri 0 51.9 .07 51.9, c(l) m(i) lpattern(dash) lcolor(gs10)) || ///
(kdensity forecast_trim if treatment_all==1, lcolor(black) ///
text(.058 42 "Mean: 50.3%", color(gs2) orientation(horizontal) placement(6)) ///
text(.005 62 "True result: 51.9%", color(gs10) orientation(horizontal) placement(6)))


**********
*Appendix A

*
*Table A1. Summary statistics
*Leave forecast
sum forecast if treatment_all==1, detail
sum forecast if treatment_all==1 [iweight=weight_modified]
*Leave forecast trimmed
sum forecast_trim if treatment_all==1, detail
sum forecast_trim if treatment_all==1 [iweight=weight_modified]
*Forecast accuracy
sum accuracy_abs if treatment_all==1, detail
sum accuracy_abs if treatment_all==1 [iweight=weight_modified]
*Forecast accuracy (squared)
sum accuracy_sq if treatment_all==1, detail
sum accuracy_sq if treatment_all==1 [iweight=weight_modified]
*socio-demo
tab education2, gen(edu)
tab ethnicity, gen(ethn)
tab income6, gen(incomedum)
tab party4_des, gen(partydum)
tab brexit_vote, gen(votedum)
sum female Age edu1 edu2 edu3 edu4 ethn1 ethn2 ///
incomedum1 incomedum2 incomedum3 incomedum4 incomedum5 incomedum6 day_int ///
attention partydum1 partydum2 partydum3 partydum4 votedum1 votedum2 votedum3 votedum4


*
*Table A2. Correlates of Leave forecasts
eststo clear
eststo: reg forecast100 $demo i.edu_high i.att_high ib1.vote3 day_int2 i.party4_des i.route [pweight=W8]
eststo: reg forecast100 $demo i.edu_high##ib1.vote3 i.att_high day_int2 i.party4_des i.route [pweight=W8]
eststo: reg forecast100 $demo i.edu_high i.att_high##ib1.vote3 day_int2 i.party4_des i.route [pweight=W8]
esttab using "~TableA2.rtf", ///
b(%6.3f) se(%6.3f) starlevels(* .05 ** .01 *** .001) scalars (r2_a r2_p bic aic) title("Table A2") wide compress noeqlines replace 



*********
*Figure 2: Forecast share of “Leave” votes by voting preferences and education
*Same models as in Table A2

eststo clear
*all
reg forecast100 $demo i.edu_high i.att_high ib1.vote3 day_int2 i.party4_des i.route [pweight=W8]
margins 1.vote3 2.vote3, post
coefplot, recast(bar) barwidth(0.5) vert scheme(plottig) title("All respondents") ///
yscale(range(42(2)58)) ylabel(42(2)58) ///
xtitle("Voting intentions in Brexit referendum") ytitle("Forecasts of Leave votes") citop name(all, replace)
*low edu
reg forecast100 $demo i.edu_high##ib1.vote3 i.att_high day_int2 i.party4_des i.route [pweight=W8]
margins 1.vote3 2.vote3, at(edu_high==0) post
coefplot, recast(bar) barwidth(0.5) vert scheme(plottig) title("Low education") ///
yscale(range(42(2)58)) ylabel(42(2)58) ///
xtitle("Voting intentions in Brexit referendum") ytitle("") citop name(low_edu, replace)
*high edu
reg forecast100 $demo i.edu_high##ib1.vote3 i.att_high day_int2 i.party4_des i.route [pweight=W8]
margins 1.vote3 2.vote3, at(edu_high==1) post
coefplot, recast(bar) barwidth(0.5) vert scheme(plottig) title("High education") ///
yscale(range(42(2)58)) ylabel(42(2)58) ///
xtitle("Voting intentions in Brexit referendum") ytitle("") citop name(high_edu, replace)
*combine
graph combine all low_edu high_edu, graphregion(color(white))


*
*Table A3. Correlates of forecast accuracy 
sum accuracy_sq accuracy_abs
eststo clear
*squared forecast error
eststo: reg accuracy_sq $demo i.education2 day_int2 attention i.party4_des i.brexit_vote i.route [pweight=W8]
*absolute forecast error
eststo: reg accuracy_abs $demo i.education2 day_int2 attention i.party4_des i.brexit_vote i.route [pweight=W8]
esttab using "~TableA3.rtf", ///
b(%6.3f) se(%6.3f) starlevels(* .05 ** .01 *** .001) scalars (r2_a r2_p bic aic) title("Table A3") wide compress noeqlines replace 


*************
*Figure 3. Correlates of forecast accuracy (model 1 in table A3)
reg accuracy_sq i.female age10 i.education2 ib2.ethnicity i.income6 day_int2 attention i.party4_des i.times1 i.route [pweight=W8]
reg accuracy_sq $demo i.education2 day_int2 attention i.party4_des i.brexit_vote i.route [pweight=W8]
coefplot, drop(*route _cons) xline(0, lpattern(dash) lcolor(gs10)) graphregion(color(white)) omitted baselevels ///
xtitle("Correlates of forecast accuracy")


*
*Table A4. Correlates of forecast accuracy and Leave forecasts (experimental sample only)
eststo clear
*squared forecast error
eststo: reg accuracy_sq $demo i.edu_high day_int i.att_high ib1.vote3 i.route if treatment!=. [pweight=W8]
*absolute error
eststo: reg accuracy_abs $demo i.edu_high day_int i.att_high ib1.vote3 i.route if treatment!=. [pweight=W8]
*leave forecasts
eststo: reg forecast100 $demo i.edu_high day_int i.att_high ib1.vote3 i.route if treatment!=. [pweight=W8]
*interaction with edu
eststo: reg forecast100 $demo i.edu_high##ib1.vote3 day_int i.att_high i.route if treatment!=. [pweight=W8]
*interaction with attention
eststo: reg forecast100 $demo i.edu_high i.att_high##ib1.vote3 day_int i.route if treatment!=. [pweight=W8]
esttab using "~TableA4.rtf", ///
b(%6.2f) se(%6.2f) starlevels(* .05 ** .01 *** .001) scalars (r2_a r2_p bic aic) title("TableA4") wide compress noeqlines replace 


*
*Table A5. Correlates of Leave (vs. Remain) votes - bandwagon effect
eststo clear
eststo: logit vote_leave forecast100 $demo i.education2 day_int2 i.route [pweight=W8]
eststo: logit vote_leave forecast100 $demo i.education2 day_int2 i.route i.party4_des c.prior_att [pweight=W8]
esttab using "~TableA5.rtf", ///
b(%6.3f) se(%6.3f) starlevels(* .05 ** .01 *** .001) scalars (r2_a r2_p bic aic) title("Table A5. Correlates of Leave (vs. Remain) votes") wide compress noeqlines replace 


*
*Table A6. Correlates of likelihood to turnout at Brexit referendum
gen forecast_close = (-abs(forecast100-50))+50
fre forecast_close // the higher, the closer the prediction to 50%
eststo clear
eststo: reg turnout_brexit forecast_close $demo i.education2 day_int2 i.route [pweight=W8]
eststo: reg turnout_brexit forecast_close $demo i.education2 day_int2 i.route i.party4_des i.brexit_vote [pweight=W8]
esttab using "~TableA6.rtf", ///
b(%6.3f) se(%6.3f) starlevels(* .05 ** .01 *** .001) scalars (r2_a r2_p bic aic) title("Table A6. Correlates of likelihood to turnout at Brexit referendum") wide compress noeqlines replace 




